Handling Events
Although the Java applet runs within its own runtime environment, it must often interact with events that occur in the Mac OS. For example, user events (such as mouse clicks) or system events may require some response from the Java program. This section describes JManager functions for handling such events. For more information about how the Mac OS handles events, see "Event Manager" in Inside Macintosh: Macintosh Toolbox Essentials.Actions performed on a frame may need to be reflected on the user-visible window as well, but in most cases, such actions are handled by JManager through a callback. For example, if the user clicks on an applet window's close box, your application must notify the frame that this has occurred. The Java program can then take action based upon this event, such as removing the frame or displaying a message in a dialog box. In either case, the AWT uses the callback functions you defined in your application to display the results. Figure 1-4 shows the steps for removing an applet window.
Figure 1-4 Removing an applet window
See "Displaying Frames" for more information about using the callbacks.
When an event occurs, you typically call an event-handling function from your main loop. Listing 1-12 shows an example of an event-handling function.
static void handleEvent(const EventRecord* eve) { switch (eve->what) { case updateEvt: handleUpdate((WindowPtr) eve->message); break; case activateEvt: handleActivate((eve->modifiers & activeFlag) != 0, (WindowPtr) eve->message); break; case osEvt: /* everyone should care about this */ handleResume((eve->message & resumeFlag) != 0); break; case kHighLevelEvent: AEProcessAppleEvent(eve); break; case mouseDown: handleMouse(eve); break; /* assume no one cares about these */ case mouseUp: break; case keyDown: case autoKey: case keyUp: handleKey(eve); break; } }High-level events (generally Apple events) are handled by calling the Mac OS Toolbox functionAEProcessAppleEvent
. In other cases, the handling functions should check to see if the event needs to be passed to the embedded Java program. The sections that follow describe the JManager functions needed to pass events and give sample implementations of thehandleUpdate
,handleActivate
,handleResume
,handleMouse
, andhandleKey
functions.Update, Activate, and Resume Events
If the application receives an update event, it must update the currently active window. If the window corresponds to a frame, you must pass the update event to the frame using theJMFrameUpdate
function. The AWT context can then update the actual window using a callback. Listing 1-13 shows an example of an update function.Listing 1-13 Handling a frame update event
static void handleUpdate(WindowPtr win) { JMFrameRef frame; BeginUpdate(win); SetPort(win); frame = (JMFrameRef) GetWRefCon(win); if (frame) JMFrameUpdate(frame, win->visRgn); else EraseRgn(win->visRgn); EndUpdate(win); }If an activate event occurs, then a window was made active (that is, brought to the front), and if that window is associated with a frame, you must activate the frame using theJMFrameActivate
function. This action gives the frame the opportunity to highlight title bars, scroll bars, and so on. Activating a frame also installs the menu bar associated with the frame. Listing 1-14 gives an example of activating a frame.Listing 1-14 Sending an activate event to a frame
static void handleActivate(Boolean active, WindowPtr window) { JMFrameRef frame = (JMFrameRef) GetWRefCon(window); if (frame) JMFrameActivate(frame, active); }Suspend and resume events can also occur when a window is activated or deactivated. When the user switches from one application to another, the newly selected application is sent a resume event, and the previously active one is sent a suspend event. This event affects all the applets embedded within an application, so you must call the
- Note
- The
JMFrameActivate
function can either activate or deactivate a frame, depending on the Boolean value passed to it (the value ofactive
in this example).![]()
JMFrameResume
function to suspend or resume all the existing frames.Listing 1-15 shows how to send a resume event to all the frames associated with a client application.
Listing 1-15 Sending a resume event to frames
static void handleResume(Boolean resume) { WindowPtr win = FrontWindow(); while (win) { JMFrameRef frame = (JMFrameRef) GetWRefCon(win); if (frame) JMFrameResume(frame, resume); win = (WindowPtr) ((WindowPeek) win)->nextWindow; } }This example cycles through all the visible windows used by the application and sends the event to those associated with frames. However, this example only works if every frame is associated with a window. If this is not the case, you must use some other method to send the resume event.
- Note
- The
JMFrameResume
function can either suspend or resume a frame, depending on the Boolean value passed to it (the value ofresume
in this example).![]()
Mouse Events
A mouse event occurs when you click somewhere in the visible screen area. A function that handles mouse events must check the location of the mouse click and take action as appropriate. If the mouse event took place in a window that corresponds to a frame, you must pass the event to the frame so the Java applet can take proper action.Listing 1-16 shows a function,
handleMouse
, that handles a mouse event.Listing 1-16 Handling a mouse event
void handleMouse(const EventRecord* eve) { WindowPtr win; short part = FindWindow(eve->where, &win); switch (part) { case inMenuBar: { long mResult = MenuSelect(eve->where); if (mResult != 0) menuHit(mResult >> 16, mResult & 0xffff); } break; case inDesk: break; case inSysWindow: SystemClick(eve, win); break; case inContent: if (win != FrontWindow()) SelectWindow(win); else { JMFrameRef frame = (JMFrameRef) GetWRefCon(win); if (frame) { /* convert the mouse position to window local */ /* coordinates and pass it into the Java */ /* environment */ Point localPos = eve->where; SetPort(win); GlobalToLocal(&localPos); JMFrameClick(frame, localPos, eve->modifiers); } } break; case inDrag: { Rect r = (**GetGrayRgn()).rgnBBox; DragWindow(win, eve->where, &r); } break; case inGoAway: { /* request that the frame go away--it will call to the */ /* frame through a callback if it actually does */ JMFrameRef frame = (JMFrameRef) GetWRefCon(win); if (frame) JMFrameGoAway(frame); } break; case inGrow: { union GrowResults { Point asPt; long asLong; } results; JMFrameRef frame = (JMFrameRef) GetWRefCon(win); Rect rGrow = { 30, 30, 5000, 5000 }; results.asLong = GrowWindow(win, eve->where, &rGrow); if (frame != nil && results.asLong != 0) { /* request that the frame resize itself--it will call */ /* to the frame through a callback if it actually does */ Rect r; r.left = 0; r.top = 0; r.right = results.asPt.h; r.bottom = results.asPt.v; r.bottom -= 15; JMSetFrameSize(frame, &r); } } break; default: break; } }This example uses the Mac OS Toolbox functionFindWindow
to determine the location of the mouse click and then takes action depending on the location.The
inMenuBar
,inDesk
, andinSysWindow
cases are handled as in any Mac OS application.If the mouse click occurs in a window's content area (
inContent
),handleMouse
checks to see if the window is active. If not, the window is selected (it receives an activate event and possibly a resume event). If the window is currently active, the local position of the mouse within the window is calculated and the coordinates sent to the corresponding frame using theJMFrameClick
function. In a similar manner, you can also send a mouse-over event by calling the
JMFrameMouseOver
function before theJMIdle
call in the main event loop.If the mouse click is in the drag region (
inDrag
), the Mac OS Toolbox functionDragWindow
is called to move the window. You do not have to pass any information to the corresponding frame, since the Java runtime environment does not worry about the relative position of frames.If the mouse click is on the close box (
inGoAway
), the code notifies the corresponding frame using theJMFrameGoAway
function. Any user-visible response to this action (such as removing the window) is handled by the AWT using the callbacks you specified when instantiating the AWT context.If the mouse click is in a window's size box (
inGrow
), the code calls the Mac OS Toolbox functionGrowWindow
to track the new size of the window. The new dimensions are passed to the frame using theJMSetFrameSize
function. The dimensions of the window are updated using an AWT context callback.
- Note
- If the new window dimensions are too large or too small (because of screen constraints or some arbitrary limit), the window should be adjusted to a preferred size.
![]()
Keyboard Events
Keyboard events occur whenever the user presses a key. These keypresses may correspond to text entered into a window, a keyboard-equivalent menu selection, or a similar action (for example, selecting the default button in a dialog box by pressing the return key). If the keyboard event occurs in a window that corresponds to a frame, you must pass the event to the frame using either theJMFrameKey
function for key-down events or theJMFrameKeyRelease
function for key-up events.Listing 1-17 shows a simple example that handles a keyboard event.
Listing 1-17 Handling a keyboard event
static void handleKey(const EventRecord* eve) { WindowPtr win; JMFrameRef frame; /* see if a menu item was selected */ if (eve->what == keyDown && (eve->modifiers & cmdKey) == cmdKey) { long menuResult = MenuKey(eve->message & charCodeMask); if (menuResult != 0) { menuHit(menuResult >> 16, menuResult & 0xffff); return; } } /* otherwise, just let JManager deal with it */ win = FrontWindow(); if (win) { frame = (JMFrameRef) GetWRefCon(win); if (frame) JMFrameKey(frame, eve->message & charCodeMask, (eve->message & keyCodeMask) >> 8, eve->modifiers); } }This code first checks to see if the keyboard input was a keyboard equivalent for a menu item (for example, Command-Q for Quit). If so, control passes to the menu-event routine (see Listing 1-18 for an example of handling a menu selection). In all other cases, the keyboard input is passed to the frame corresponding to the window, and the Java program can then determine the appropriate response. The content of the keyboard input is determined from the event record (theEventRecord
structure) returned by the Event Manager.Menu Selections
Both mouse events and keyboard events can select menu items. In either case, the event should be handled by a menu selection function. If the selection corresponds to a Java applet's menu item, you must pass the selection to the applet's AWT context using theJMMenuSelected
function. Listing 1-18 shows a simple menu selection function.Listing 1-18 Handling a menu item selection
/* enumerators to define the Mac OS menus*/ enum Menus { eAppleMenu = 1000, eFileMenu, eEditMenu, eLastMenu }; /* enumerators to define the menu items */ enum AppleMenuItems { eAboutItem = 1 }; enum FileMenuItems { eMyAction1 = 1,/* nonstandard menu item defined by */ /* the application */ eQuitItem = eMyAction1 + 2 }; enum EditMenuItems { eUndoItem = 1, eCutItem = eUndoItem + 2, eCopyItem, ePasteItem, eClearItem, eSelectAllItem = eClearItem + 2 }; static void menuHit(short menuID, short menuItem) { switch (menuID) { case eAppleMenu: switch (menuItem) { case eAboutItem: /* show About box */ MyAboutBox(); break; default: { /* open the appropriate desk accessory */ Str255 s; SetPort(LMGetWMgrPort()); GetItem(GetMHandle(eAppleMenu), menuItem, s); if (s[0] > 0) OpenDeskAcc(s); } break; } break; case eFileMenu: switch (menuItem) { case eMyAction1: DoMyAction1(); break; case eQuitItem: MainEventLoopContinues = false; break; } break; case eEditMenu: break; default: { /* pass the menu hit to the AWTContext for processing */ WindowPtr win = FrontWindow(); if (win != nil) { JMFrameRef frame = (JMFrameRef) GetWRefCon(win); if (frame != nil) { JMAWTContextRef context = JMGetFrameContext(frame); if (context != nil) JMMenuSelected(context, GetMHandle(menuID), menuItem); } } } break; } HiliteMenu(0); }If the user did not select a standard menu item, themenuHit
function passes the menu selection to the applet's AWT context. On the Mac OS, the menu bar is always associated with the active window (and, consequently, with the active frame). After determining the frame associated with the window (using the Mac OS Toolbox functionGetWRefCon
),JMGetFrameContext
returns the AWT context associated with the frame. The menu handle of the selection is then passed to the AWT context using theJMMenuSelected
function.Drag-And-Drop Support
If your embedding application supports the Drag Manager, you can pass drag-and-drop information to a frame using JManager functions. TheJMFrameDragTracking
function allows your frame to respond to an item dragged over it (for example, creating a highlight to signal that the drag item is valid for the frame). If the user drops the item within the frame boundaries, theJMFrameDragReceive
function lets you pass information about the dropped item to the frame.These functions correspond respectively to the application-defined Drag Manager functions
DragTrackingHandler
andDragReceiveHandler
, and are called from within these handlers. For more information about the Drag Manager, see the Drag Manager Programmer's Guide.
- Note
- The Java JDK standards 1.1.x and earlier do not support drag and drop.
![]()
Subtopics
- Update, Activate, and Resume Events
- Mouse Events
- Keyboard Events
- Menu Selections
- Drag-And-Drop Support